package com.huiquan.analysis.tree;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

/**
 * TODO Put here a description of what this class does.
 * 
 * @author renhao.cao Create 2016年5月10日.
 */
public class AhoCorasickDoubleArrayTrieHelper {

	/** AC自动机 */
	private AhoCorasickDoubleArrayTrie<String> acdat;

	public AhoCorasickDoubleArrayTrieHelper(String[] keyArray) {
		acdat = buildASimpleAhoCorasickDoubleArrayTrie(keyArray);
	}

	/**
	 * 构建一个自动机双数组字典树.
	 * 
	 * @param keyArray
	 * @return
	 */
	private AhoCorasickDoubleArrayTrie<String> buildASimpleAhoCorasickDoubleArrayTrie(String[] keyArray) {
		// Collect test data set
		TreeMap<String, String> map = new TreeMap<String, String>();
		for (String key : keyArray) {
			map.put(key, key);
		}
		// Build an AhoCorasickDoubleArrayTrie
		AhoCorasickDoubleArrayTrie<String> acdat = new AhoCorasickDoubleArrayTrie<String>();
		acdat.build(map);
		return acdat;
	}

	/**
	 * 在基于自动机的双数组字典树中匹配字符串.
	 * 
	 * @param acdat
	 * @param text
	 * @return
	 */
	private List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> validateASimpleAhoCorasickDoubleArrayTrie(
			AhoCorasickDoubleArrayTrie<String> acdat, String text) {
		List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> wordList = acdat.parseText(text);

		return wordList;
	}

	/**
	 * 找到队列中长度最长的词.
	 * 
	 * @param wordList
	 * @return
	 */
	private AhoCorasickDoubleArrayTrie<String>.Hit<String> getEffectWords(
			List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> wordList,
			List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> effectWords) {
		int sum = 0;
		AhoCorasickDoubleArrayTrie<String>.Hit<String> effectWord = null;
		for (AhoCorasickDoubleArrayTrie<String>.Hit<String> word : wordList) {
			int begin = word.begin;
			int end = word.end;
			// 将位置与有效词有重叠部分的词都过滤
			boolean flag = true;
			for (AhoCorasickDoubleArrayTrie<String>.Hit<String> eff : effectWords) {
				if ((begin >= eff.begin && begin < eff.end) || (end > eff.begin && end < eff.end)) {
					flag = false;
					break;
				}
			}
			if (flag) {
				int length = end - begin;
				if (length > sum) {
					sum = length;
					effectWord = word;
				}
			}
		}
		return effectWord;
	}

	/**
	 * 获取最长匹配词.
	 * 
	 * @param text
	 * @return
	 */
	public List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> getMatchWords(String text) {
		List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> wordList = validateASimpleAhoCorasickDoubleArrayTrie(acdat,
				text);

		// 找出最长匹配词,其余不做计算
		// 取匹配长度最长的词作为有效词
		List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> effectiveWords = new ArrayList<AhoCorasickDoubleArrayTrie<String>.Hit<String>>();

		boolean stopFlag = true;
		while (stopFlag) {
			AhoCorasickDoubleArrayTrie<String>.Hit<String> effectWord = getEffectWords(wordList, effectiveWords);
			if (effectWord == null)
				stopFlag = false;
			else
				effectiveWords.add(effectWord);
		}

		return effectiveWords;
	}

	/**
	 * 获取全匹配词.
	 * 
	 * @param text
	 * @return
	 */
	public List<String> getAllMatchWords(String text) {
		List<String> words = new ArrayList<String>();
		List<AhoCorasickDoubleArrayTrie<String>.Hit<String>> wordList = validateASimpleAhoCorasickDoubleArrayTrie(acdat,
				text);
		for (AhoCorasickDoubleArrayTrie<String>.Hit<String> hit : wordList) {
			words.add(hit.value);
		}

		return words;
	}

}
